﻿using System;
using System.Collections.Generic;

namespace Levfier.Proccessors.Chains
{
    /// <summary>
    /// 接続を行うクラス
    /// </summary>
    [Serializable]
    public class Chain : IChainable
    {
        //排他制御用のオブジェクト
        private object lockObject;

        /// <summary>
        /// 後段の処理クラスリスト
        /// </summary>
        private IList<IProccessable> proccessors;

        /// <summary>
        /// バッファ
        /// </summary>
        protected double[] buffer;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Chain()
        {
            //リストを生成する
            this.proccessors = new List<IProccessable>();
            this.lockObject = new object();
        }

        /// <summary>
        /// 後段の処理に音を流す
        /// </summary>
        public void FlowSounds()
        {
            lock (this.lockObject)
            {
                foreach (IProccessable proccessor in proccessors)
                {
                    proccessor.Proccess(this.buffer);
                }
            }
        }

        /// <summary>
        /// バッファを取得する
        /// </summary>
        /// <returns>バッファ</returns>
        public double[] GetBuffer()
        {
            return this.buffer;
        }

        /// <summary>
        /// 後段の処理クラスを追加する
        /// </summary>
        /// <param name="proccessor">追加対象の処理クラス</param>
        public void SetProccessor(IProccessable proccessor)
        {
            lock (this.lockObject)
            {
                this.proccessors.Add(proccessor);

                //プロセッサに接続したことを通知する
                proccessor.NotifyConnect(this);
            }
        }

        /// <summary>
        /// 後段の処理クラスを削除する
        /// </summary>
        /// <param name="proccessor">削除対象の処理クラス</param>
        /// <returns>true : 成功、 false : 失敗</returns>
        public bool RemoveProccessor(IProccessable proccessor)
        {
            lock (this.lockObject)
            {
                //プロセッサに切断を通知する
                proccessor.NotifyDisconnect(this);
                return this.proccessors.Remove(proccessor);
            }
        }
    }
}
